//
// Created by jingyuewu on 25-8-18.
//
#include <boost/asio.hpp>
#include <ctime>
#include <iostream>
#include <string>
#include <chrono>
#include "debug_utils.h"

using boost::asio::ip::tcp;

std::string make_daytime_string() {
  using namespace std;
  time_t now = time(0);
  return ctime(&now);
}

class TcpConnection : public std::enable_shared_from_this<TcpConnection> {
public:
  using Pointer = std::shared_ptr<TcpConnection>;

  static Pointer create(boost::asio::io_context &io_context) {
    return Pointer(new TcpConnection(io_context));
  }

  tcp::socket &socket() { return socket_; }

  void start() {
    DEMO_DEBUG("enter start");
    message_ = make_daytime_string();
    boost::asio::async_write(socket_, boost::asio::buffer(message_),
                             std::bind(&TcpConnection::handle_write,
                                       shared_from_this(),
                                       std::placeholders::_1, std::placeholders::_2));
    DEMO_DEBUG("leave start");
  }

private:
  TcpConnection(boost::asio::io_context &io_context)
      : socket_(io_context), timer_(io_context)
  {
    DEMO_DEBUG("enter TcpConnection Ctor");
  }
  
  void handle_write(const boost::system::error_code &error, size_t bytes_transferred) {
    DEMO_DEBUG("enter handle_write");
    if (!error) {
      // 使用异步定时器替代 sleep，避免阻塞线程
      timer_.expires_after(std::chrono::seconds(1));
      timer_.async_wait(std::bind(&TcpConnection::handle_timer,
                                  shared_from_this(),
                                  std::placeholders::_1));
    } else {
      DEMO_DEBUG("Error in handle_write: " + error.message());
      // 连接已关闭，对象将被销毁
    }
    DEMO_DEBUG("leave handle_write");
  }

  void handle_timer(const boost::system::error_code &error) {
    DEMO_DEBUG("enter handle_timer");
    if (!error) {
      message_ = make_daytime_string();
      // 检查socket连接状态
      if (socket_.is_open()) {
        try {
          std::cout << "send message: " << message_ << " to " << socket_.remote_endpoint() << std::endl;
        } catch (const std::exception& e) {
          std::cout << "send message: " << message_ << " to remote_endpoint: " << e.what() << std::endl;
        }
        boost::asio::async_write(socket_, boost::asio::buffer(message_),
                                 std::bind(&TcpConnection::handle_write,
                                           shared_from_this(),
                                           std::placeholders::_1,
                                           std::placeholders::_2));
      } else {
        std::cout << "Socket is not open, stopping write loop" << std::endl;
      }
    } else {
      DEMO_DEBUG("Error in handle_timer: " + error.message());
    }
    DEMO_DEBUG("leave handle_timer");
  }

  tcp::socket socket_;
  boost::asio::steady_timer timer_;
  std::string message_;
};

class TcpServer {
public:
  TcpServer(boost::asio::io_context & io_context)
      : io_context_(io_context),
        acceptor_(io_context, tcp::endpoint(tcp::v4(), 17239)) {
    DEMO_DEBUG("enter TcpServer Ctor");
    start_accept();
  }

private:
  void start_accept() {
    DEMO_DEBUG("enter start_accept");
    TcpConnection::Pointer new_connection = TcpConnection::create(io_context_);

    acceptor_.async_accept(new_connection->socket(),
                           std::bind(&TcpServer::handle_accept, this,
                                     new_connection, std::placeholders::_1));
    DEMO_DEBUG("Leave start_accept()");
  }

  void handle_accept(TcpConnection::Pointer new_connection,
                     const boost::system::error_code &error) {
    DEMO_DEBUG("enter handle_accept");
    if (!error) {
      new_connection->start();
    } else {
      DEMO_DEBUG("Error in handle_accept: " + error.message());
    }
    // 添加对acceptor状态的检查，确保仍在监听连接
    if (!error && acceptor_.is_open()) {
      start_accept();
    }
    DEMO_DEBUG("leave handle_accept");
  }

  boost::asio::io_context & io_context_;
  tcp::acceptor acceptor_;
};

int main() {
  try {
    boost::asio::io_context io_context;
    TcpServer server(io_context);
    io_context.run();
  } catch (std::exception &e) {
    std::cerr << e.what() << std::endl;
  }
  return 0;
}